package de.aeo.bll;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.nio.charset.Charset;
import java.util.ArrayList;

/**
 * @author Frederic Branczyk & Robert Piwonski
 */
public class Import {

    // begin of attributes
    private ArrayList<Student> students;
    private ArrayList<Subject> subjects;
    private Manager m;
    // end of attributes


    // begin of methods
      
    // Contructor
    /**
     * Loads data from a table file (csv).
     * 
     * Loads data, that was either saved from a previous session or 
     * created manually regarding the manual's data formation guide, into the GUI.
     * @param subjectsAlreadyExisting Subjects that were already created in the GUI.
     */
    public Import(ArrayList<Subject> subjectsAlreadyExisting, Manager m){
        this.students = new ArrayList<Student>();// Create a new list of students, old ones will be lost
        this.subjects = subjectsAlreadyExisting; // Keep subjects already entered
        this.m = m;
    }

    /**
     * Evaluates a given file. Creates students and subjects.
     * @param improperDataExceptionMsg_1 An error caused by improper data formation.
     * @param improperDataExceptionMsg_2 An error caused by improper data formation.
     * @param pleaseAddSubjectTitle Current translation of the phrase that shall remind the user of editing the standard name of a subject. 
     * @param file The file selected by the user.
     * @throws MalformedURLException
     * @throws ImproperDataException
     * @throws FileNotFoundException
     * @throws IOException
     */
    public void importData(File file) throws MalformedURLException, ImproperDataException, FileNotFoundException, IOException {
        InputStreamReader in = new InputStreamReader(new FileInputStream(file), Charset.forName("ISO-8859-1"));
        BufferedReader reader = new BufferedReader(in);
        String readString;
        int line = 0;
        while ((readString = reader.readLine()) != null) {
            line++;
            String[] buffer = readString.split(";"); // rather ';' than ',' since there might be last names as "Münchhausen, von"
            if (buffer[0].contains("//") || readString.equals("")){ // Is this commented, empty or irrelevant data ?
                continue; // Then skip it !
            }
            // Check data for errors
            if((buffer.length < 4 && buffer.length != 2)|| buffer.length > 9){
            // Wrong input format or corrupted data
            // Show user there is something wrong with his data and where he needs to fix it
                throw new ImproperDataException(this.m.getLanguage().getString("improperDataExceptionMsg_1") + line + this.m.getLanguage().getString("improperDataExceptionMsg_2"));
            }
            
            try { // First of all, is this a subject ?
                if(buffer.length == 2){
                // It's just a student with a first name and last name, no wishes, yet.
                throw new NumberFormatException(); // This leads to creating a student instead of a subject.
                }
                int min = Integer.parseInt(buffer[2]); // Exception will be thrown if there is no number. Number means this line represents a subject.
                int max = Integer.parseInt(buffer[3]);

                if(notExistingYet(buffer[1])){ // Is there already a subject with this abbreviation ?                      
                    int periodInt;
                    if (buffer[1].contains("2")){ // Is this subject taking both years ? Should be marked in the abbreviation.
                        periodInt = 2;
                        buffer[1] = buffer[1].substring(0, buffer[1].length()-1);
                    }else{ // Nope. Just one year.
                        periodInt = 1;
                    }
                    // Having collected all relevant data, create the subject !   
                    this.subjects.add(new Subject(buffer[0], buffer[1], min, max, periodInt));
                }
            }
            catch(NumberFormatException nfe) { // It's a student.
                Subject[] studentsSubjects = {null, null, null, null, null, null};
                // Match the subjects chosen by the student.
                for(int a = 3; a < buffer.length; a++){
                // If they do not exist, yet, create them with standard parameters to be edited, later 
                    if(!buffer[a].equals("") && notExistingYet(buffer[a])){
                        int periodInt;
                        if (buffer[a].contains("2")){
                            periodInt = 2;
                            buffer[a] = buffer[a].substring(0, buffer[a].length()-1);
                        }else{
                            periodInt = 1;
                        }
                        this.subjects.add(new Subject(this.m.getLanguage().getString("pleaseAddSubjectTitle"), buffer[a], 10, 20, periodInt));    
                    }
                    // Match the subjects, now they exist, for sure.
                    if (!buffer[a].equals("")){
                       studentsSubjects[a-3] = getSubjectByAbbreviation(buffer[a]);
                    }
                }
                // Having collected all relevant data and taken care of the data integrity, create the student.
                this.students.add(new Student(buffer[0],buffer[1],buffer[2],studentsSubjects));            
            }
        }
        // No return value since two lists have to be returned. They can be accessed by using the get-methods.
    }

    private boolean notExistingYet(String abbreviation){
        for (Subject s : this.subjects) {                
            if(abbreviation.equals(s.getAbbreviation()+s.getPeriodAbbreviation())){
                return false; // Subject found.
            }
        }	
        return true; // Subject not found.
    }

    private Subject getSubjectByAbbreviation(String abbreviation){
        for (Subject s : this.subjects) {                
            if(abbreviation.equals(s.getAbbreviation()+s.getPeriodAbbreviation())){
                return s; // Subject found and can be worked with. Will always happen.
            }
        }
        return subjects.get(0); // Definately won't happen. This line is irrelvant, but Java asks for it. 
    }

    /**
     * 
     * @return The imported subjects in a list.
     */
    public ArrayList<Subject> getSubjects(){
        return this.subjects;
    }

    /**
     * 
     * @return The imported students in a list.
     */
    public ArrayList<Student> getStudents(){
        return this.students;
    }
    // end of methods
}